package com.billdowney.util.properties;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

import com.billdowney.util.ConstParams;
import com.billdowney.util.DateUtil;

/**
 * @Description: properties文件工具类
 * @author: 唐路钧
 * @date: 2018年9月7日 上午11:45:46
 */
public class PropertiesFileUtil {

	/**
	 * 资源路径关键字
	 */
	private final String classPathKeyword = "classpath:";
	/**
	 * 传入的文件路径，例：classpath:xxx.properties；C:\\xxx.properties
	 */
	private String filePath = "";
	/**
	 * 当前读取的文件内容
	 */
	private SafeProperties properties = new SafeProperties();
	/**
	 * 默认文件编码
	 */
	private String charsetName = ConstParams.SYSTEM_CHARSET_NAME;

	/**
	 * @Description: 传入的文件路径来得到文件内容的工具类
	 * @param filePath 文件路径，例：classpath:xxx.properties；C:\\xxx.properties
	 * @throws IOException
	 */
	public PropertiesFileUtil(String filePath) throws IOException {
		this.filePath = filePath;
		loadProperties(filePath);
	}

	/**
	 * @Description: 传入的文件路径来得到文件内容的工具类
	 * @param filePath    文件路径，例：classpath:xxx.properties；C:\\xxx.properties
	 * @param charsetName 文件的编码，例：UTF-8
	 * @throws IOException
	 */
	public PropertiesFileUtil(String filePath, String charsetName) throws IOException {
		this.filePath = filePath;
		this.charsetName = charsetName;
		loadProperties(filePath);
	}

	/**
	 * @Description: 加载properties文件内容
	 * @param filePath    文件路径，例：classpath:xxx.properties；C:\\xxx.properties
	 * @param charsetName 文件的编码，例：UTF-8
	 * @throws IOException
	 * @author: 唐路钧
	 * @date: 2018年9月7日 下午2:19:04
	 */
	private void loadProperties(String filePath) throws IOException {
		InputStream in = null;
		if (filePath.contains(classPathKeyword)) {
			in = PropertiesFileUtil.class.getClassLoader()
					.getResourceAsStream(filePath.replaceFirst(classPathKeyword, ""));
		} else {
			in = new FileInputStream(filePath);
		}
		properties.load(in, charsetName);
		if (in != null) {
			in.close();
		}
	}

	/**
	 * @Description: 打印所有key和对应的value
	 * @author: 唐路钧
	 * @date: 2018年9月7日 下午2:20:44
	 */
	public void printAllKeyAndValue() {
		for (Object key : properties.keySet()) {
			System.out.println(key + ":" + properties.getProperty(key.toString()));
		}
	}

	/**
	 * @Description: 传入键值来写入数据，会更新文件
	 * @param key   键名
	 * @param value 键值
	 * @return 是否成功
	 * @author: 唐路钧
	 * @date: 2018年9月7日 下午2:31:06
	 */
	public boolean put(String key, String value) {
		return put(key, value, "更新：" + key + "，值：" + value + "，时间：" + DateUtil.getCurrentDate(), null);
	}

	public boolean put(String key, String value, String keyDesc) {
		return put(key, value, keyDesc, null);
	}

	public boolean put(String key, String value, String keyDesc, String headDesc) {
		OutputStream fos = null;
		try {
			// 调用 Hashtable 的方法 put，使用 getProperty 方法提供并行性。
			// 强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。
			if (filePath.contains(classPathKeyword)) {
				fos = new FileOutputStream(PropertiesFileUtil.class.getClassLoader()
						.getResource(filePath.replaceFirst(classPathKeyword, "")).getPath());
			} else {
				fos = new FileOutputStream(filePath);
			}
			// 以适合使用 load 方法加载到 Properties 表中的格式，
			// 将此 Properties 表中的属性列表（键和元素对）写入输出流
			properties.putAndComment(key, value, keyDesc);
			properties.store(fos, headDesc, charsetName);
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
					return false;
				}
			}
		}
		return true;
	}

	public String getProperty(String key) {
		return properties.getProperty(key);
	}

	public String getProperty(String key, String defaultValue) {
		return properties.getProperty(key, defaultValue);
	}

	public Integer getInteger(String key) throws NumberFormatException {
		return Integer.parseInt(this.getProperty(key));
	}

	public Float getFloat(String key) throws NumberFormatException {
		return Float.parseFloat(this.getProperty(key));
	}

	public Double getDouble(String key) throws NumberFormatException {
		return Double.parseDouble(this.getProperty(key));
	}

	public String getFilePath() {
		return filePath;
	}

	public Properties getProperties() {
		return properties;
	}

}
